<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN" xml:lang="zh_CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../rurple.css" type="text/css" />

<title>再一次避免重复</title>
</head>
<body>
<h2 class="title">11. 再一次避免重复</h2>

<p>在前面一堂课中我们所看到规则 #3 是很重要的，所以这里我希望再重复一下，这样可以使你们更好地记住。</p>

<dl>
<dt><b>法则3</b></dt>
<dd>在写计算机程序时，要避免不必要的重复。<br />重申一遍: <b>要避免不必要的重复！</b></dd>
</dl>

<!--================================================-->
<hr class="line" />

<a name="Repeat" id="Repeat"></a>
<h3 class="section">新的命令：重复</h3>

<p>在上一节课里面的报纸分发的小实验中，其实仍然可以看到有不少的重复。 例如, 命令 <tt>turn_left()</tt> 可能在定义 <tt>turn_right()</tt>的定义中出现了三次. 而 <tt>climb_up_one_stair()</tt>可能在 <tt>climb_up_four_stairs()</tt>的定义中出现了四次. 这似乎和我们所说的“不要重复”的规则是相悖的。 一种防止这种重复的方法是使机器人通过一个特殊的命令来自动重复命令。</p>

<p>我们用命令 <tt>repeat()</tt> 来让机器人自动重复一个命令： <tt>repeat(</tt> <em>命令名称</em>, 次数<tt>)</tt></p>

<p>注意：<em>命令的名称</em>的后面是没有圆括号（）的。 例如，如果我们希望定义“右转”为重复三次左转的话，我们要写：</p>

<pre>
<span class="keyword">def</span> turn_right():
    repeat(turn_left, 3)
</pre>

<h3 class="try">轮到你了</h3>

<p>在报纸分发练习中，现在一起来利用 <tt>repeat()</tt>命令，你可以写出一个更短的程序版本来。当然要确认你的新程序和预期效果一样。</p>

<!--============================================-->
<hr class="line" />

<a name="Challenges2" id="Challenges2"></a>
<h3 class="suggested">挑战来了！</h3>

<p>这堂课的最后我们希望大家一起来做一些小实验。 根据本堂课的主题（而不是标题！），首先头两个练习是重复了砌墙那堂课最后我们进行的两个练习。 你必须使用这堂课和上堂课所学的新概念 [<span class="pykeyword">def</span>, <tt>repeat()</tt>] 换句话说，我们将利用定义和重复这两个Python的关键词来解决问题。</p>

<h3 class="suggested">小实验（一）：跨栏</h3>

<p>乐跑机器人参加了一个跨栏比赛。 请写一个程序让它根据如下所示的路径到达终点线。 世界文档是 hurdles1.wld。</p>

<div class="pcenter"><img alt="hurdles start" src=
"../../images/intro/hurdles1_start.png" /></div>
<div class="pcenter"><img alt="lead to" src="../../images/lead_to.png" /> <img alt=
"hurdles end" src="../../images/intro/hurdles1_end.png" /></div>

<p>这里,我们可以根据如下所示的路径定义一个新命令 <tt>jump_hurdle()</tt>：意思是跳过障碍物</p>

<div class="pcenter"><img alt="jump one hurdle start" src=
"../../images/intro/jump1start.png" /> <img alt="lead to" src=
"../../images/lead_to.png" /> <img alt="jump one hurdle end" src=
"../../images/intro/jump1end.png" /></div>

<p>将你的新程序和原来的进行比较。 [你确认已经将它保存了，是吧?]</p>

<!--=====================================================-->
<hr class="line" />

<h3 class="suggested">小实验（二）：丰收时刻</h3>

<p>现在是丰收的季节！ 如下图所示，机器人要捡起花园里所有的胡萝卜（图中用圆圈表示），请先打开世界文档 harvest1.wld。</p>

<p><img alt="harvest start" src="../../images/intro/harvest1.png" /></p>

<p>你的程序应该定义如下命令：</p>

<pre>
<span class="comment"># 移动到第一行</span>
move_to_first_row()
<span class="comment"># 收成两行</span>
harvest_two_rows()
<span class="comment"># 右转到下一行</span>
move_right_to_next_row()
</pre>

<p>你可能想更深一步细化这些命令；例如，你 <b><i>可以</i></b> ：</p>

<pre>
<span class="comment"># 收成两行</span>
<span class="keyword">def</span> harvest_two_rows():
    <span class="comment"># 收成一行</span>
    harvest_one_row()
    <span class="comment"># 移动到左面到第二行</span>
    move_left_to_next_row()
    <span class="comment"># 收成一行</span>
    harvest_one_row()
</pre>

<p>前提是要给 <code>harvest_one_row()</code>一个合适的定义. 然而，你可以用你自己的方法来细化这些必要的命令。 有了这三个必要的命令，我的程序如下所示：（当然还是有一点重复的）</p>

<pre>
<span class="comment"># 移动到第一行</span>
move_to_first_row()
<span class="comment"># 收成两行</span>
harvest_two_rows()
<span class="comment"># 右转到下一行</span>
move_right_to_next_row()
<span class="comment"># 收成两行</span>
harvest_two_rows()
<span class="comment"># 右转到下一行</span>
move_right_to_next_row()
<span class="comment"># 收成两行</span>
harvest_two_rows()
<span class="comment"># 关机</span>
turn_off()
</pre>

<p>现在，再次将你的新程序和以前的收获时刻小实验的程序进行比较。</p>

<h3 class="suggested">小实验（三）：又是丰收时刻了！</h3>

<p>哈哈，又到了收获季节了！ 然而，这次花园里的胡萝卜是对角摆放的。 如下图所示，机器人要捡起花园里所有的胡萝卜（图中用报警器来表示） ，请大家打开世界文档 harvest2.wld.</p>

<p><img alt="harvest start" src="../../images/intro/harvest2.png" /></p>

<p>像之前的例子，你的程序应该定义了如下的命令：</p>

<pre>
move_to_first_row()
harvest_two_rows()
move_right_to_next_row()
</pre>

<p>这些命令将 <b><u>不再</u></b>像之前定义的一样。 然而，一旦这些命令已经定义好了，你的程序可能就和之前的例子中的是一样的：</p>

<pre>
move_to_first_row()
harvest_two_rows()
move_right_to_next_row()
harvest_two_rows()
move_right_to_next_row()
harvest_two_rows()
turn_off()
</pre>

<p>注意千万不要撞墙！ 考虑一下你想从哪里开始收获和你准备收获的方向。 或许在一张纸上画一张草图让你可以先实习一下。</p>

<div class="lessons_nav">
<a href="10-def.htm"><img alt="previous" src=
"../../images/previous.png" /> 利用定义来避免重复</a> - <a href=
"../lessons_toc.htm"><img alt="home" src="../../images/home.png" /></a> - <a href=
"12-if.htm">假如乐跑可以自己作决定... <img alt="next" src=
"../../images/next.png" /></a>
</div>
</body>
</html>
